﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;

namespace snake
{
    public enum direction
    {
        上 = 0,
        下 = 1,
        左 = 2,
        右 = 3
    }

    public partial class snakeForm : BaseForm
    {
        #region 私有变量
        private int snakeBodySize = 20;

        private int snakeBodyLength = 4;

        /// <summary>
        /// 蛇身
        /// </summary>
        private List<Label> snakeBody = new List<Label>();

        /// <summary>
        /// 食物
        /// </summary>
        private Label food = new Label();

        private direction snakeHeadDirection = direction.右;

        private int containerWidth = 800;

        private int containerHeigth = 600;
        #endregion

        #region 私有方法
        private void createBody(bool isHead = false, Point? newPoint = null)
        {
            Label label = new Label();
            if (isHead)
            {
                //蛇头坐标
                label.Location = new Point(7 * snakeBodySize, 7 * snakeBodySize);
                label.BackColor = Color.FromArgb(255, 87, 34);
            }
            else
            {
                label.Location = newPoint ?? new Point(snakeBody.Last().Location.X - snakeBodySize, snakeBody.Last().Location.Y);
                label.BackColor = System.Drawing.Color.White;
            }

            label.Size = new System.Drawing.Size(snakeBodySize, snakeBodySize);
            label.TabIndex = 0;
            this.snakeBody.Add(label);
            this.Controls.Add(label);
        }

        private void createFood()
        {
            Point point;
            do
            {
                point = nextPoint();
            }
            while (snakeBody.Exists(m => m.Location.X == point.X && m.Location.Y == point.Y));

            food.Location = point;
            food.BackColor = Color.Green;
            food.Size = new System.Drawing.Size(snakeBodySize, snakeBodySize);
            food.TabIndex = 0;
        }

        private Point nextPoint()
        {
            Random random = new Random();
            int X = random.Next(0, containerWidth / snakeBodySize);
            int Y = random.Next(0, containerHeigth / snakeBodySize);
            return new Point(X * snakeBodySize, Y * snakeBodySize);
        }

        private void snakeMove()
        {
            Point point = snakeBody.First().Location;
            switch (snakeHeadDirection)
            {
                case direction.上:
                    point.Y -= snakeBodySize;
                    break;
                case direction.下:
                    point.Y += snakeBodySize;
                    break;
                case direction.左:
                    point.X -= snakeBodySize;
                    break;
                case direction.右:
                    point.X += snakeBodySize;
                    break;
                default:
                    break;
            }
            for (int i = snakeBody.Count - 1; i > 0; i--)
            {
                snakeBody[i].Location = snakeBody[i - 1].Location;
            }

            #region 可穿墙版本
            if (point.X < 0)
            {
                point.X = containerWidth - snakeBodySize;
            }
            if (point.Y < 0)
            {
                point.Y = containerHeigth - snakeBodySize;
            }
            if (point.X >= containerWidth)
            {
                point.X = 0;
            }
            if (point.Y >= containerHeigth)
            {
                point.Y = 0;
            }
            #endregion
            snakeBody.First().Location = point;
            //移动到身体的情况
            if (snakeBody.Where(m => m != snakeBody.First()).Any(m => m.Location.X == point.X && m.Location.Y == point.Y))
            {
                this.timer1.Stop();
                MessageBox.Show("你已死亡!! 分数：" + label1.Text);
            }
            //移动到边界的情况 
            #region 不可穿墙
            //if (point.X < 0 || point.Y < 0 || point.X >= containerWidth || point.Y >= containerHeigth)
            //{
            //    this.timer1.Stop();
            //    MessageBox.Show("你已死亡!! 分数：" + label1.Text);
            //} 
            #endregion
            //吃到食物的情况
            if (point.X == food.Location.X && point.Y == food.Location.Y)
            {
                createBody(newPoint: snakeBody.Last().Location);
                createFood();
                label1.Text = Convert.ToInt32(label1.Text) + 1 + "";
                timer1.Interval--;//加速
            }
        }
        #endregion

        public snakeForm()
        {
            InitializeComponent();
            StartGame();
        }

        private void StartGame()
        {
            Random random = new Random();
            int index = random.Next(0, 4);
            //初始化蛇的头的位置
            //snakeHeadDirection = (direction)index;
            snakeHeadDirection = direction.右;

            foreach (var item in snakeBody)
            {
                this.Controls.Remove(item);
            }
            snakeBody.Clear();
            for (int i = 0; i < snakeBodyLength; i++)
            {
                createBody(i == 0);
            }
            timer1.Start();
            createFood();
            this.Controls.Add(food);
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            snakeMove();
        }

        private void 关闭ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.ExitThread();
        }

        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            switch (keyData)
            {
                case Keys.Up:
                    snakeHeadDirection = snakeHeadDirection == direction.下 ? snakeHeadDirection : direction.上;
                    break;
                case Keys.Down:
                    snakeHeadDirection = snakeHeadDirection == direction.上 ? snakeHeadDirection : direction.下;
                    break;
                case Keys.Left:
                    snakeHeadDirection = snakeHeadDirection == direction.右 ? snakeHeadDirection : direction.左;
                    break;
                case Keys.Right:
                    snakeHeadDirection = snakeHeadDirection == direction.左 ? snakeHeadDirection : direction.右;
                    break;
                default:
                    break;
            }
            return base.ProcessCmdKey(ref msg, keyData);
        }

        private void 暂停ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Stop();
        }

        private void Stop()
        {
            if (暂停ToolStripMenuItem.Text == "暂停")
            {
                暂停ToolStripMenuItem.Text = "开始";
                this.timer1.Stop();
            }
            else
            {
                暂停ToolStripMenuItem.Text = "暂停";
                this.timer1.Start();
            }
        }

        private void 最小化ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            minimize();
        }

        private void minimize()
        {
            this.WindowState = FormWindowState.Minimized;
            暂停ToolStripMenuItem.Text = "开始";
            this.timer1.Stop();
        }

        private void 重新开始ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            StartGame();
        }

        private void snakeForm_DoubleClick(object sender, EventArgs e)
        {
            minimize();
        }

        private void snakeForm_Click(object sender, EventArgs e)
        {
            暂停ToolStripMenuItem.Text = "暂停";
            this.timer1.Start();
        }
    }

}
